#ifndef AUTOTEST_H
#define AUTOTEST_H

#include <QTest>
#include <QList>
#include <QString>
#include <QSharedPointer>

#include <QFile>
#include <QTextStream>
#include <QDebug>

namespace AutoTest
{
typedef QList<QObject*> TestList;

inline TestList &testList()
{
    static TestList list;
    return list;
}

inline bool findObject(QObject *object)
{
    TestList &list = testList();
    if (list.contains(object))
    {
        return true;
    }
    foreach (QObject *test, list)
    {
        if (test->objectName() == object->objectName())
        {
            return true;
        }
    }
    return false;
}

inline void addTest(QObject *object)
{
    TestList &list = testList();
    if (!findObject(object))
    {
        list.append(object);
    }
}

inline int run(int argc, char *argv[])
{
    int ret = 0;

#ifdef TEST_LOG
    Q_UNUSED(argc);

    QString logName = TEST_LOG;
    QFile cleanFile(logName);
    cleanFile.open(QIODevice::WriteOnly);
    cleanFile.close();

    foreach (QObject *test, testList())
    {
        QFile readFile(logName);
        readFile.open(QIODevice::ReadOnly);
        QTextStream tsRead(&readFile);
        QString buffer = tsRead.readAll();

        QByteArray bytes = logName.toAscii();
        char *new_argv[3];
        char arg1[] = "-o";
        new_argv[0] = argv[0];
        new_argv[1] = arg1;
        new_argv[2] = bytes.data();

        ret += QTest::qExec(test, 3, new_argv);

        QFile writeFile(logName);
        writeFile.open(QIODevice::WriteOnly | QIODevice::Append);
        QTextStream tsOut(&writeFile);
        tsOut << buffer << endl;
    }
#else
    foreach (QObject *test, testList())
    {
        ret += QTest::qExec(test, argc, argv);
    }
#endif

    return ret;
}
}

template <class T>
class Test
{
public:
    QSharedPointer<T> child;

    Test(const QString &name) : child(new T)
    {
        child->setObjectName(name);
        AutoTest::addTest(child.data());
    }
};

#define DECLARE_TEST(className) static Test<className> t(#className);

#define TEST_MAIN \
    int main(int argc, char *argv[]) \
    { \
    return AutoTest::run(argc, argv); \
    }

#endif // AUTOTEST_H
